package com.carrot.gateway.util;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.carrot.common.enums.ErrorCodeEnum;
import com.carrot.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import reactor.core.publisher.Flux;

import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 获取POST body
 *
 * @author 周鹏程
 * @date 2023-05-09 5:54 PM
 **/
@Slf4j
public final class GetPostBodyUtil {

    public static JSONObject getBodyToJson(ServerHttpRequest sourceRequest) throws ServiceException {
        //从请求里获取Post请求体
        String bodyStrJson = resolveBodyFromRequest(sourceRequest);
        // 只针对post请求处理
        if(!HttpMethod.POST.matches(sourceRequest.getMethodValue())){
            log.error("请求参数不合法 ---- 不是post请求");
            throw new ServiceException(ErrorCodeEnum.CODE_ERROR_METHOD_ARGUMENT_NOT_VALID);
        }

        if(!JSONUtil.isJson(bodyStrJson)){
            log.error("请求参数不合法 ---- Data JSON为空 => {}", bodyStrJson);
            throw new ServiceException(ErrorCodeEnum.CODE_ERROR_METHOD_ARGUMENT_NOT_VALID);
        }

        JSONObject httpBodyJson = JSONUtil.parseObj(bodyStrJson);
        if(JSONUtil.isNull(httpBodyJson)){
            log.error("请求参数不合法 ---- Data JSON为空 => {}", bodyStrJson);
            throw new ServiceException(ErrorCodeEnum.CODE_ERROR_METHOD_ARGUMENT_NOT_VALID);
        }
        return httpBodyJson;
    }

    /**
     * 从Flux<DataBuffer>中获取字符串的方法
     * @return 请求体
     */
    public static String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
        //获取请求体
        Flux<DataBuffer> body = serverHttpRequest.getBody();

        AtomicReference<String> bodyRef = new AtomicReference<>();
        body.subscribe(buffer -> {
            CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
            DataBufferUtils.release(buffer);
            bodyRef.set(charBuffer.toString());
        });
        //获取request body
        return bodyRef.get();
    }

    private GetPostBodyUtil(){}
}
